﻿using DDD_Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using System.IdentityModel.Tokens.Jwt;

namespace DDD_Extensions;

public static class OAuthAuthenticationExtension
{
    public static IServiceCollection AddOAuthAuthentication(this IServiceCollection service, OAuthSchemeOption oAuthSchemeOption)
    {
        service.AddAuthentication(config =>
        {
            config.DefaultAuthenticateScheme = oAuthSchemeOption.DefaultAuthenticateScheme;
            config.DefaultSignInScheme = oAuthSchemeOption.CookieScheme;
            config.DefaultChallengeScheme = oAuthSchemeOption.DefaultChallengeScheme;
        })
        .AddCookie(oAuthSchemeOption.CookieScheme)
        .AddOAuth(oAuthSchemeOption.OAuthScheme, config =>
        {
            config.CallbackPath = oAuthSchemeOption.OAuthOption.CallbackPath;
            config.ClientId = oAuthSchemeOption.OAuthOption.ClientId;
            config.ClientSecret = oAuthSchemeOption.OAuthOption.ClientSecret;
            config.AuthorizationEndpoint = oAuthSchemeOption.OAuthOption.AuthorizationEndpoint;
            config.TokenEndpoint = oAuthSchemeOption.OAuthOption.TokenEndpoint;
            if (oAuthSchemeOption.OAuthOption != null && oAuthSchemeOption.OAuthOption.Scopes.Any())
            {
                foreach (var item in oAuthSchemeOption.OAuthOption.Scopes)
                    config.Scope.Add(item);
            }

            config.SaveTokens = true;

            config.Events = new Microsoft.AspNetCore.Authentication.OAuth.OAuthEvents()
            {
                OnCreatingTicket = context =>
                {
                    if (!string.IsNullOrEmpty(context.AccessToken))
                    {
                        JwtSecurityToken jwt = new JwtSecurityTokenHandler().ReadJwtToken(context.AccessToken);

                        if (jwt.Payload != null && jwt.Payload.Any())
                        {
                            context.Identity!.AddClaims(jwt.Payload.Claims);
                        }
                    }

                    return Task.CompletedTask;
                }
            };
        });

        return service;
    }
}

